home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / gif.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  25KB  |  1,033 lines

  1. /*
  2.  * $Id: gif.c,v 0.91 1994/02/20 00:52:50 zhao Pre-Release $
  3.  *
  4.  *. This file is part of BIT shareware package. After the two weeks of
  5.  *  free evaluation period, you are encouraged (required) to register
  6.  *  your copy for a small registration fee, which is $35 for personal use
  7.  *  and $50 for commercial, government and institutional use.
  8.  *
  9.  *  Copyright(c) 1993, 1994 by T.C. Zhao.
  10.  *  All rights reserved.
  11.  *
  12.  *  Permission to use, copy, and distribute this software in its entirety
  13.  *  for non-commercial purposes is hereby granted, provided that the
  14.  *  above shareware and copyright notices and this permission notice
  15.  *  appear in all copies and their documentation.
  16.  *
  17.  *  This software may be modified for your own use, but modified versions
  18.  *  may not be distributed without prior consent of the author.
  19.  *
  20.  *  This software is provided "as is" without expressed or implied
  21.  *  warranty of any kind.
  22.  *
  23.  *.
  24.  *
  25.  * CompuServ GIF related routines. Basically reads raster one row a time and
  26.  * then hand the pixels to the driver via function outputline in proper
  27.  * order.
  28.  *
  29.  * BUGS:
  30.  *  Multi images are not handled. Graphics control not handled(except
  31.  *  transparency)
  32.  *
  33.  *
  34.  * "The Graphics Interchange Format(c) is the Copyright property of
  35.  *  CompuServ Incorporated. GIF(sm) is a Service Mark property of
  36.  *  CompuServ Incorporated.
  37.  *
  38.  */
  39. #ifndef NO_GIF
  40.  
  41. #if !defined(lint) && defined(F_ID)
  42. char *id_gif = "$Id: gif.c,v 0.91 1994/02/20 00:52:50 zhao Pre-Release $";
  43. #endif
  44.  
  45. #include "bit.h"
  46. #include "dmalloc.h"
  47.  
  48. static long gif_rlines;        /* No. of lines read so far */
  49. /********************************************************************
  50.  * Given GIF sequence no. i, starting from 0, figure out the image
  51.  * sequence number. If interlaced, the sequence will be independent
  52.  * of i, sort of a bug, but for this application, it is perfectly ok.
  53.  *********************************************************************/
  54. static int
  55. next_lineno(int i, int h, int interlace)
  56. {
  57.     /* interlace delta */
  58.     static const int steps[5] =
  59.     {
  60.     8, 8, 4, 2, 0
  61.     };
  62.  
  63.     /* starting scanline */
  64.     static const int start[5] =
  65.     {
  66.     0, 4, 2, 1, 0
  67.     };
  68.     static int pass, sofar, current;
  69.     int line;
  70.  
  71.     /* init for each image */
  72.     if (i == 0)
  73.     pass = sofar = current = 0;
  74.  
  75.     if (!interlace)
  76.     line = i;
  77.     else
  78.       {
  79.       line = current;
  80.       if ((current += steps[pass]) >= h)
  81.           current = start[++pass];
  82.       }
  83.     sofar++;
  84.     REPORT(sofar, gif_rlines);
  85.  
  86.     /* check */
  87.     if (line >= h)
  88.       {
  89.       Bark("GIFNextLine", "Bad scan line");
  90.       return h - 1;
  91.       }
  92.     return line;
  93. }
  94.  
  95. static const unsigned int gif_codemask[] =
  96. {
  97.     0, 1, 3, 7, (1 << 4) - 1, (1 << 5) - 1, (1 << 6) - 1,
  98.     (1 << 7) - 1, (1 << 8) - 1, (1 << 9) - 1, (1 << 10) - 1,
  99.     (1 << 11) - 1, (1 << 12) - 1
  100. };
  101.  
  102. /*****************************************************************
  103.  * Decoding routines
  104.  *
  105.  * The way the master driver is setup, it is difficult to handle
  106.  * multiple images stored in a single  GIF file (which is rare).
  107.  *****************************************************************/
  108.  
  109. /******************* local functions ******************/
  110.  
  111. static int readextension(FILE *);
  112. static void read_map(CMPTR, FILE *);
  113. static int skip_extension(FILE * fp);
  114. static int process_lzw_code(int);
  115. static void outputline(unsigned char *);
  116.  
  117. /****************** decoder variables ******************/
  118.  
  119. /* this is the stuff handled by the decoder */
  120. static int transparency;
  121.  
  122. /* copies of the global variable */
  123. static IPTR gif_lm;
  124. static char *gif_ifile;
  125. static long gif_total;        /* no. of pixels read so far */
  126.  
  127. /****************************************************************
  128.  * ouptut line simply copies one scanline at a time to the master
  129.  * image structure, taking into account the possibility of
  130.  * interlacing
  131.  ****************************************************************/
  132.  
  133. static void
  134. outputline(register unsigned char *line)
  135. {
  136.     register ci_t **pp = gif_lm->mraster, *po;
  137.     register unsigned char *pi = line;
  138.     static int lines;
  139.     int k;
  140.  
  141.     if (gif_total == 0)        /* first entry */
  142.     lines = 0;
  143.  
  144.     k = next_lineno(lines, gif_lm->h, gif_lm->interlace);
  145.  
  146.     gif_total += gif_lm->w;
  147.  
  148.     for (po = pp[k], line += gif_lm->w; pi < line;)
  149.     *po++ = *pi++;
  150.     lines++;
  151. }
  152.  
  153. #define IMAGESEP      0x2C    /* ',' */
  154.  
  155. static int
  156. read_descriptor_block(IPTR im, int global_gifmap)
  157. {
  158.     int local_gifmap;
  159.     int inbyte;
  160.     unsigned char buf[15];
  161.     const char *f = "GIF_desc";
  162.     FILE *fp = im->fp;
  163.  
  164.     /*
  165.      * read the extension if any, and do nothing about it until get the image
  166.      * separator
  167.      */
  168.  
  169.     if (skip_extension(fp) != IMAGESEP)
  170.       {
  171.       Bark(f, "%s: No separator or BadBlockMarker", gif_ifile);
  172.       return -1;
  173.       }
  174.  
  175.     /* offset has no meaning, skip it, gif_total 2 + 2= 4bytes */
  176.  
  177.     if (Badfread(buf, 1, 4, fp))
  178.     return -1;
  179.  
  180.     /* True image size */
  181.     im->w = get2LSBF(fp);
  182.     im->h = get2LSBF(fp);
  183.  
  184.     inbyte = getc(fp);
  185.     im->interlace = (inbyte & 0x40) != 0;
  186.     local_gifmap = (inbyte & 0x80);
  187.     set_iformat_info(im, im->interlace ? "Interlaced" : "");
  188.     if (!global_gifmap && !local_gifmap)
  189.       {
  190.       Bark(f, "%s: No ColorMap", gif_ifile);
  191.       /* return -1; *//* might want to continue */
  192.       }
  193.  
  194.     /* if local map, replace the global map */
  195.     if (local_gifmap)
  196.       {
  197.       local_gifmap = (inbyte & 0x07) + 1;
  198.       im->cmap->colors = (1 << local_gifmap);
  199.       read_map(im->cmap, fp);
  200.       }
  201.     return 0;
  202. }
  203.  
  204. /**********************************************************************
  205.  * Get GIF image descriptions
  206.  **********************************************************************/
  207.  
  208. int
  209. GIF_desc(IPTR im)
  210. {
  211.     int global_gifmap;
  212.     unsigned char buf[15];
  213.     FILE *fp = im->fp;
  214.  
  215.     gif_lm = im;
  216.     gif_ifile = im->ifile;
  217.     transparency = 0;
  218.  
  219.     /* img_open should have checked signature Skip it. total  6 bytes */
  220.     if (Badfread(buf, 1, 6, fp))
  221.     return -1;
  222.  
  223.     /* now the packed field */
  224.     if (Badfread(buf, 1, 7, fp))
  225.     return -1;
  226.  
  227.     /*
  228.      * primary color resolution doesn't mean too much here ignore it. Also
  229.      * bit 4 under 89a could  be 1, so ignore that too.
  230.      */
  231.  
  232.     im->lsx = buf[0] + (buf[1] << 8);
  233.     im->lsy = buf[2] + (buf[3] << 8);
  234.  
  235.     global_gifmap = (buf[4] & 0x80);
  236.     im->colors = im->cmap->colors = 1 << (1 + (buf[4] & 0x07));
  237.     im->cmap->ucolors = im->colors;
  238.     /* im->bkcolor= buf[5]; */
  239.  
  240.     im->aspect = buf[6] ? (1000.0 * (buf[6] + 15) / 64.0) : 1000;
  241.     /* err= buf[4] & 0x08; */
  242.  
  243.     if (global_gifmap)
  244.     read_map(im->cmap, fp);
  245.  
  246.     /*
  247.      * supposedly, from here to EOS (';'), the data stream may be repeated
  248.      * more than one times, currently, the program does not handle this,
  249.      * maybe a next field in IPTR ?????
  250.      */
  251.  
  252.     return read_descriptor_block(im, global_gifmap);
  253. }
  254.  
  255. /* Get a single data block.  */
  256. static int
  257. getblock(FILE * fp, char *buf)
  258. {
  259.     int count;
  260.  
  261.     if ((count = getc(fp)) != EOF && count != 0)
  262.     count = fread(buf, 1, count, fp);
  263.     return count;
  264. }
  265.  
  266. #define EXTENSION     0x21    /* '!'  introducer  */
  267. #define GIFEXT_PT     0x01    /* plain text       */
  268. #define GIFEXT_APP    0xFF    /* application      */
  269. #define GIFEXT_GC     0xF9    /* graphics control */
  270. #define GIFEXT_COM    0xFE    /* comment          */
  271. #define Bad_ext(str) Bark(f,"%s: Bad %s extension",gif_ifile,str)
  272. #define Msg_ext(str) M_info(gif_ifile,str)
  273.  
  274. /*
  275.  * As long as we are not doing the extension, print it out to stderr
  276.  */
  277. static int
  278. readextension(FILE * fp)
  279. {
  280.     int count = 0, label;
  281.     char buf[258];
  282.     const char *f = "GIF_ext";
  283.     int ll, tt, cw, ch, bc, tc;
  284.     float fsize;
  285.  
  286.     label = getc(fp);
  287.     switch (label)
  288.       {
  289.       case GIFEXT_PT:        /* plain text extension */
  290.  
  291.       Msg_ext("PlainText extension");
  292.       if (getc(fp) != 12)
  293.         {
  294.         Bad_ext("PlainText");
  295.         return EOF;
  296.         }
  297.  
  298.       ll = get2LSBF(fp);    /* left         */
  299.       tt = get2LSBF(fp);    /* top          */
  300.       get2LSBF(fp);        /* total width  */
  301.       get2LSBF(fp);        /* total height */
  302.       cw = getc(fp);    /* cell width   */
  303.       ch = getc(fp);    /* cell height  */
  304.       tc = getc(fp);    /* text color   */
  305.       bc = getc(fp);    /* bk color     */
  306.  
  307.       while ((count = getblock(fp, buf)) != 0 && count != EOF)
  308.         {
  309.         rgba_t ttc, bbc;
  310.  
  311.         buf[count] = '\0';
  312.         M_warn(gif_ifile, buf);
  313.         fsize = Min(cw, ch);
  314.  
  315.         if (fsize < 6.0)
  316.             fsize = 6.0;
  317.         ttc = Pack(gif_lm->cmap->ct[0][tc], gif_lm->cmap->ct[1][tc],
  318.                gif_lm->cmap->ct[2][tc]);
  319.         bbc = Pack(gif_lm->cmap->ct[0][bc], gif_lm->cmap->ct[1][bc],
  320.                gif_lm->cmap->ct[2][bc]);
  321.         img_add_text(gif_lm, buf, "", fsize, 0.0, ttc,
  322.               ll, (tt - fsize), !transparency, bbc, 0, 0, 0, 0);
  323.         }
  324.       break;
  325.  
  326.       case GIFEXT_COM:        /* a comment extension */
  327.  
  328.       Msg_ext("CommentsExtension:");
  329.       while ((count = getblock(fp, buf)) != 0 && count != EOF)
  330.         {
  331.         buf[count] = '\0';
  332.         Msg_ext(buf);
  333.         }
  334.       break;
  335.  
  336.       case GIFEXT_GC:        /* graphics control     */
  337.  
  338.       Msg_ext("GraphicsControl extension");
  339.       while ((count = getblock(fp, buf)) != 0 && count != EOF)
  340.         {
  341.         transparency = (buf[0] & 1);    /* packed bytes */
  342.         }
  343.       break;
  344.  
  345.       case GIFEXT_APP:        /* application extension */
  346.  
  347.       Msg_ext("ApplicationExtension");
  348.       if (getc(fp) != 11)    /* block length */
  349.           M_warn("GifExt", "wrong block length");
  350.  
  351.       fread(buf, 1, 8, fp);
  352.       buf[8] = '\0';
  353.       Msg_ext(buf);
  354.       fread(buf, 1, 3, fp);
  355.       while ((count = getblock(fp, buf)) != 0 && count != EOF)
  356.         {
  357.         buf[count] = '\0';
  358.         Msg_ext(buf);
  359.         }
  360.       break;
  361.  
  362.       default:
  363.       Bark(f, "%s: Bogus extension byte 0x%02x", gif_ifile, label);
  364.       break;
  365.       }
  366.     return count;
  367. }
  368.  
  369. static int
  370. skip_extension(FILE * fp)
  371. {
  372.     int pchar, err = 0;
  373.  
  374.     while (!err && (pchar = getc(fp)) != EOF && pchar != IMAGESEP)
  375.       {
  376.       switch (pchar)
  377.         {
  378.         case '\0':
  379.         break;
  380.         case EXTENSION:
  381.         err = readextension(fp);
  382.         break;
  383.         default:
  384.         M_warn("GIFextension", "%s: Bogus byte 0x%02x",
  385.                gif_ifile, pchar);
  386.         return EOF;
  387.         }
  388.       }
  389.     return err ? EOF : pchar;
  390. }
  391.  
  392. static void
  393. read_map(CMPTR m, FILE * fp)
  394. {
  395.     register pc_t *r = m->ct[0], *g = m->ct[1], *b = m->ct[2], *rs;
  396.  
  397.     for (rs = r + m->colors; r < rs; r++, g++, b++)
  398.       {
  399.       *r = getc(fp);
  400.       *g = getc(fp);
  401.       *b = getc(fp);
  402.       }
  403. }
  404.  
  405. #define LZW_INIT          9000
  406. static int bpp, ClearCode, EOFCode, CodeSize;
  407. static const char *lfn = "GIF_load";
  408.  
  409. #include <ctype.h>
  410. static unsigned char *lhead, *lbuf, *stackp;    /* local buffers */
  411.  
  412. int
  413. GIF_load(IPTR im)
  414. {
  415.     register int bits = 0, err, count, code = -1;
  416.     register unsigned datum = 0;
  417.     register unsigned char *ch;
  418.     unsigned char buf[257];
  419.     FILE *fp = im->fp;
  420.  
  421.     gif_rlines = progress_report("Loading GIF...", im->h);
  422.  
  423.     CodeSize = getc(fp);
  424.     if (CodeSize > 8 || CodeSize < 2)
  425.       {
  426.       Bark(lfn, "%s: Bad CodeSize: %d", gif_ifile, CodeSize);
  427.       return -1;
  428.       }
  429.  
  430.     /* initialize the decompressor */
  431.     err = gif_total = 0;
  432.     (void) process_lzw_code(LZW_INIT);
  433.  
  434.     while (!err && (count = getc(fp)) != EOF && count > 0)
  435.       {
  436.       err = Badfread(buf, 1, count, fp);
  437.       for (ch = buf; !err && count-- > 0; ch++)
  438.         {
  439.         datum += *ch << bits;
  440.         bits += 8;
  441.         while (bits >= CodeSize && !err)
  442.           {
  443.               code = datum & gif_codemask[CodeSize];
  444.               datum >>= CodeSize;
  445.               bits -= CodeSize;
  446.               err = (code == EOFCode) || process_lzw_code(code) ||
  447.               (gif_total > (long) im->w * im->h);
  448.           }
  449.         }
  450.       if (err && code == EOFCode)
  451.           err = 0;
  452.       if (code != EOFCode && gif_total > (long) im->w * im->h)
  453.         {
  454.         Bark(lfn, "%s: Raster full before EOI", gif_ifile);
  455.         err = 1;
  456.         }
  457.       }
  458.  
  459.     if (!err)
  460.       {
  461.       if ((code = getc(fp)) == EXTENSION)
  462.         {
  463.         ungetc(code, fp);
  464.         while ((code = skip_extension(fp)) != EOF && code != IMAGESEP)
  465.             ;
  466.         }
  467.       if (code == IMAGESEP)
  468.         {
  469.         Bark(lfn, "%s: More than one image present", gif_ifile);
  470.         }
  471.       else if (code != EOF &&
  472.            ((fread(buf, 1, 50, fp), getc(fp))) != EOF)
  473.         {
  474.         M_info(lfn, "%s: Garbage(> 50bytes) at end", gif_ifile);
  475.         ch = buf;
  476.         while (ch - buf < 50)
  477.           {
  478.               fputc(isprint(*ch) ? *ch : ' ', fp);
  479.               ch++;
  480.           }
  481.         }
  482.       }
  483.  
  484.     remove_progress_report();
  485.     im->t2b = 1;
  486.  
  487.     count = gif_total / im->w;
  488.  
  489.     /* final check: get pixels that are decoded but yet to be output */
  490.     if (count < im->h)
  491.       {
  492.       int leftover;
  493.       leftover = lbuf - lhead;
  494.       M_warn(lfn, "total %ld should be %d", (gif_total + leftover),
  495.          im->w * im->h);
  496.       if (leftover)
  497.           outputline(lhead);
  498.       }
  499.  
  500.     /*
  501.      * if more than 1/5 image is read, return positive value so that driver
  502.      * will try to display it.
  503.      */
  504.  
  505.     return (count >= (im->h / 5)) ? count : -1;
  506. }
  507.  
  508. /*********************************************************************
  509.  * process_lzw_code - Process a compression code.  "clear" resets the
  510.  * code table. Otherwise make a new code table entry, and output the
  511.  * bytes associated with the code.
  512.  *
  513.  * Based on gifpaste by Kipp Hickman @ Silicon Graphics
  514.  */
  515. #define OUTPIX(c)   *lbuf++ = (c)
  516. #define MC_SIZE      4097
  517.  
  518. static int
  519. process_lzw_code(register int code)
  520. {
  521.     register int incode, i;
  522.     static unsigned char firstchar;
  523.     static unsigned char stack[MC_SIZE];
  524.     static int avail, oldcode;
  525.     static unsigned char suffix[MC_SIZE];
  526.     static unsigned short prefix[MC_SIZE];
  527.  
  528.  
  529.     if (code == LZW_INIT)
  530.       {
  531.       if (!lhead)
  532.           lbuf = lhead = malloc((gif_lm->w + 1 + 4096));
  533.       else
  534.           lbuf = lhead = realloc(lhead, (gif_lm->w + 1 + 4096));
  535.       bpp = CodeSize;
  536.       ClearCode = 1 << bpp;
  537.       EOFCode = ClearCode + 1;
  538.       CodeSize = bpp + 1;
  539.       for (incode = ClearCode; --incode >= 0;)
  540.         {
  541.         *(suffix + incode) = incode;
  542.         *(prefix + incode) = 0;
  543.         }
  544.       avail = ClearCode + 2;
  545.       oldcode = -1;
  546.       stackp = stack;
  547.       return lbuf ? 0 : -1;
  548.       }
  549.  
  550.     if (code == ClearCode)
  551.       {
  552.       CodeSize = bpp + 1;
  553.       avail = ClearCode + 2;
  554.       oldcode = -1;
  555.       return 0;
  556.       }
  557.  
  558.     /* this is possible only if the image file is corrupt */
  559.     if (code > avail || code < 0)
  560.       {
  561.       Bark(lfn, "%s: Bad code 0x%04.4x", gif_ifile, code);
  562.       return -1;
  563.       }
  564.  
  565.     if (oldcode == -1)
  566.       {
  567.       OUTPIX(suffix[code]);
  568.       firstchar = oldcode = code;
  569.       return 0;
  570.       }
  571.  
  572.     incode = code;
  573.     if (code == avail)
  574.       {                /* the first code is always < avail */
  575.       *stackp++ = firstchar;
  576.       code = oldcode;
  577.       }
  578.  
  579.     while (code > ClearCode)
  580.       {
  581.       *stackp++ = suffix[code];
  582.       code = prefix[code];
  583.       }
  584.  
  585.     if (avail >= 4096)
  586.       {
  587.       Bark(lfn, "%s: BadBlock -- Table full", gif_ifile);
  588.       return -1;
  589.       }
  590.     *stackp++ = firstchar = suffix[code];
  591.     prefix[avail] = oldcode;
  592.     suffix[avail] = firstchar;
  593.  
  594.     avail++;
  595.     if (((avail & gif_codemask[CodeSize]) == 0) && (avail < 4096))
  596.       {
  597.       CodeSize++;
  598.       }
  599.     oldcode = incode;
  600.     do
  601.       {
  602.       OUTPIX(*--stackp);
  603.       }
  604.     while (stackp > stack);
  605.  
  606.     /* if we've got more than one scanline, output */
  607.     incode = lbuf - lhead;
  608.     if (incode >= gif_lm->w)
  609.       {
  610.       lbuf = lhead;
  611.       while (incode >= gif_lm->w)
  612.         {
  613.         outputline(lbuf);
  614.         incode -= gif_lm->w;
  615.         lbuf += gif_lm->w;
  616.         }
  617.  
  618.       /* copy the left over */
  619.       for (i = 0; i < incode; i++)
  620.           lhead[i] = *lbuf++;
  621.       lbuf = lhead + incode;
  622.       }
  623.     return 0;
  624. }
  625.  
  626. /********************************************************************
  627.  * GIF encoding routine.
  628.  * This one I started from scratch and the only reference is the
  629.  * specification.
  630.  ********************************************************************/
  631.  
  632. static int q_color = 256;
  633. static int gifdither, method, interlace;
  634.  
  635. static int gifdump(FILE *, IPTR);    /* real encoder */
  636.  
  637. /* Driver calls this routine to write gif files */
  638. int
  639. GIF_dump(IPTR im)
  640. {
  641.     FILE *fp = im->fp;
  642.  
  643.     if (!IS_CI(im))
  644.       {                /* should be ok, check anyway */
  645.       set_quant_parameters(q_color, gifdither, method);
  646.       img_convert_type(im, im->io->type);
  647.       }
  648.  
  649.     return gifdump(fp, im);
  650. }
  651.  
  652. /************************************************************
  653.  * options for the driver: no. of colors and interlace
  654.  *************************************************************/
  655. extern const char *qstring[];
  656.  
  657. /* string version of the option */
  658. const char *
  659. GIF_wdefault(const IPTR ip)
  660. {
  661.     static char dinfo[150];
  662.  
  663.     if (IS_CPACK(ip))
  664.       {
  665.       sprintf(dinfo, "%s to %d colors. %s", qstring[method],
  666.           q_color, interlace ? "Interlace" : "");
  667.       }
  668.     else
  669.       {
  670.       sprintf(dinfo, "%d colors %s ", ip->cmap->colors,
  671.           (interlace = ip->interlace) ? "Interlace" : "");
  672.       }
  673.  
  674.     return dinfo;
  675. }
  676.  
  677. /* For colormapped image, no further quantization is allowed */
  678. int
  679. GIFdump_init(IPTR img)
  680. {
  681.  
  682.     if (!IS_CI(img))
  683.       {
  684.       set_quant_max_color(256);
  685.       get_quant_p("GIF parameters", &method, &gifdither, &q_color,
  686.               "Interlace", &interlace, 0, 0);
  687.       set_quant_parameters(q_color, gifdither, method);
  688.       }
  689.     else
  690.     interlace = !interlace;
  691.  
  692.     img->interlace = interlace;
  693.     return 0;
  694. }
  695.  
  696. /************************************************************
  697.  *
  698.  * Write image to a disk file in GIF format.
  699.  *
  700.  ************************************************************/
  701.  
  702. /*
  703.  * current char, cchar, must be of signed type, and code and prefix must be
  704.  * at least 12 bits long.
  705.  */
  706. typedef struct strspace_
  707. {
  708.     struct strspace_ *next;    /* link          */
  709.     int code;            /* emit code     */
  710.     int cchar;            /* current char */
  711. }
  712. Strtab;
  713.  
  714. typedef struct
  715.   {
  716.       int prefix, cchar, code;
  717.   }
  718. WorkStr;
  719.  
  720. #define  MAXTABL  4097
  721. static Strtab *strtab[MAXTABL], strspace[MAXTABL];
  722.  
  723. /**************************************************************
  724.  * Check if current string is already in the string table
  725.  **************************************************************/
  726. static int
  727. in_table(register WorkStr * cstr)
  728. {
  729.     register Strtab *p = strtab[cstr->prefix];
  730. #if 1
  731.     for (; p && (p->cchar != cstr->cchar); p = p->next)
  732.     ;
  733.     return p ? p->code : -1;
  734. #else
  735.     for (; p; p = p->next)
  736.     if (p->cchar == cstr->cchar)
  737.         return p->code;
  738.     return -1;
  739. #endif
  740. }
  741.  
  742. #define USE_TAB_FUNC
  743.  
  744. /*
  745.  * A macro and function are supplied to insert a string into the
  746.  * string table.
  747.  */
  748.  
  749. #ifdef USE_TAB_FUNC
  750. static void
  751. addto_table(register WorkStr * cstr, register int code)
  752. {
  753.     register Strtab *p = &strspace[code];
  754.  
  755.     p->code = code;
  756.     p->cchar = cstr->cchar;
  757.     p->next = strtab[cstr->prefix];
  758.     strtab[cstr->prefix] = p;
  759. }
  760.  
  761. #else
  762.  
  763. #define  addto_table(cstr, ccode)                           \
  764.     do {                                                    \
  765.          register Strtab *p = &strspace[ccode];             \
  766.          p->code = ccode;                                   \
  767.          p->cchar = cstr->cchar;                            \
  768.          p->next = strtab[cstr->prefix];                    \
  769.          strtab[cstr->prefix] = p;                          \
  770.    } while(ZERO)
  771. #endif
  772.  
  773. static void output_lzw_code(unsigned code);
  774. static void init_table(int);
  775. static ci_t *get_scan_line(IPTR, int);
  776.  
  777. static FILE *fp;
  778.  
  779. /*******************************************************************
  780.  * Write colormaps. Also takes care the cases where the entries
  781.  * in colormap is not 2^n, need to pad it to 2^n, otherwise, the
  782.  * encoder chokes.
  783.  *******************************************************************/
  784. static void
  785. write_map(CMPTR m, FILE * ffp)
  786. {
  787.     register pc_t *r = m->ct[0], *g = m->ct[1], *b = m->ct[2], *rs;
  788.     register int mc = m->colors;
  789.  
  790.     for (rs = r + mc; r < rs; r++, g++, b++)
  791.       {
  792.       putc((int) *r, ffp);
  793.       putc((int) *g, ffp);
  794.       putc((int) *b, ffp);
  795.       }
  796.  
  797.     /* pad with the first entry */
  798.     for (; mc < (1 << bpp); mc++)
  799.       {
  800.       putc(m->ct[0][0], ffp);
  801.       putc(m->ct[1][0], ffp);
  802.       putc(m->ct[2][0], ffp);
  803.       }
  804.  
  805. #ifdef MTRACE
  806.     M_trace("GifWrtMap", "Appears ok - exiting");
  807. #endif
  808.  
  809. }
  810.  
  811. /*
  812.  * write the image description
  813.  */
  814. static int
  815. write_desc(IPTR im, FILE * ffp)
  816. {
  817.     int packed;
  818.     unsigned char buf[10];
  819.  
  820.     /* get bits per pixel first */
  821.     bpp = 0;
  822.     while (im->cmap->colors > (1 << bpp))
  823.     bpp++;
  824.  
  825.     if (bpp < 1 || bpp > 8)
  826.       {
  827.       Bark("GIF_dump", "%s: Bad bpp=%d", im->ofile, bpp);
  828.       bpp = 1;
  829.       }
  830.  
  831.     if (Badfwrite("GIF87a", 1, 6, ffp))
  832.       {
  833.       Bark("GIF_dump", im->ofile);
  834.       return -1;
  835.       }
  836.  
  837.     put2LSBF(im->lsx, ffp);
  838.     put2LSBF(im->lsx, ffp);
  839.  
  840.     packed = 0x80        /* always output global map */
  841.     + ((bpp - 1) << 4)    /* cr. does not mean much   */
  842.     + (bpp - 1);        /* bits_per_pixel-1         */
  843.     putc(packed, ffp);
  844.     putc(0, ffp);
  845.     putc(0, ffp);        /* bk color and aspect ratio */
  846.  
  847.     /* global color map.  */
  848.     write_map(im->cmap, ffp);
  849.  
  850.     /* image descriptions  */
  851.     buf[0] = ',';        /* image seperator */
  852.     buf[1] = buf[2] = buf[3] = buf[4] = 0;    /* offsets         */
  853.     if (Badfwrite(buf, 1, 5, ffp))
  854.     return -1;
  855.  
  856.     /* raster dimensions */
  857.     put2LSBF(im->w, ffp);
  858.     put2LSBF(im->h, ffp);
  859.  
  860.     /* local_gifmap, interlace, etc. only set interlace if requested */
  861.     putc(interlace ? 0x40 : 0, ffp);
  862.  
  863. #ifdef MTRACE
  864.     M_trace("GifWrtDesc", "Appears ok - exiting");
  865. #endif
  866.  
  867.     return 0;
  868. }
  869.  
  870. /*******************************************************************
  871.  * The encoder
  872.  *******************************************************************/
  873. static int
  874. gifdump(FILE * ffp, IPTR im)
  875. {
  876.     register int j, code, ccode;
  877.     register ci_t *scan, *ss;
  878.     register WorkStr *cstr;
  879.     register int colors;
  880.     WorkStr workstring;
  881.  
  882.     fp = ffp;
  883.     gif_rlines = progress_report("Writing GIF ...", im->h);
  884.  
  885.     if (write_desc(im, fp) < 0)
  886.     return -1;
  887.  
  888.     /*
  889.      * IMPORTANT: number of colors handed to this routine might not be 2^n,
  890.      * need to make it so to fool the encoder (colors-1 need to be full bits)
  891.      */
  892.  
  893.     colors = 1 << bpp;
  894.  
  895.     /* min bpp by defination is no smaller than 2 */
  896.     if (bpp < 2)
  897.     bpp = 2;        /* initial codesize */
  898.     putc(bpp, fp);
  899.  
  900.     ClearCode = 1 << bpp;    /* set clear and end codes */
  901.     EOFCode = ClearCode + 1;
  902.     CodeSize = bpp + 1;        /* start encoding */
  903.  
  904.     init_table(colors);        /* initialize the LZW tables */
  905.     cstr = &workstring;
  906.     ccode = EOFCode + 1;
  907.     cstr->prefix = -1;
  908.  
  909.     /*
  910.      * start raster stream. Old way of doing things, that is as soon as we
  911.      * get 4095, a clearcode is emitted.
  912.      */
  913.  
  914.     for (j = 0; j < im->h; j++)
  915.       {
  916.       scan = get_scan_line(im, j);
  917.       for (ss = scan + im->w; scan < ss; scan++)
  918.         {
  919.         cstr->cchar = (*scan & (colors - 1));
  920.         if (cstr->prefix >= 0)
  921.           {
  922.               if ((code = in_table(cstr)) >= 0)
  923.             {
  924.                 cstr->prefix = code;
  925.             }
  926.               else
  927.             {
  928.                 addto_table(cstr, ccode);
  929.                 output_lzw_code(cstr->prefix);
  930.                 cstr->prefix = cstr->cchar;
  931.                 if (ccode >= (1 << CodeSize))
  932.                 CodeSize++;
  933.                 ccode++;
  934.                 if (ccode >= 4096)
  935.                   {
  936.                   output_lzw_code(cstr->prefix);
  937.                   init_table(colors);
  938.                   ccode = EOFCode + 1;
  939.                   cstr->prefix = -1;
  940.                   }
  941.             }
  942.           }
  943.         else
  944.           {        /* root entry */
  945.               cstr->prefix = cstr->code = cstr->cchar;
  946.           }
  947.         }
  948.       }
  949.     output_lzw_code(cstr->prefix);
  950.     output_lzw_code(EOFCode);
  951.     putc(0, fp);        /* end block  */
  952.     putc(';', fp);        /* end stream */
  953.     remove_progress_report();
  954.     return fflush(fp);
  955. }
  956.  
  957. static void
  958. init_table(int rootlen)
  959. {
  960.     register int i;
  961.  
  962.     output_lzw_code(ClearCode);
  963.  
  964.     CodeSize = bpp + 1;
  965.  
  966.     for (i = 0; i < rootlen; i++)
  967.       {
  968.       strspace[i].next = 0;
  969.       strspace[i].code = i;
  970.       strspace[i].cchar = -1;
  971.       strtab[i] = &strspace[i];
  972.       }
  973.  
  974.     for (; i < MAXTABL; i++)
  975.     strtab[i] = strspace[i].next = 0;
  976. }
  977.  
  978. /**************************************************************
  979.  * Packing and output an LZW code(bpp+1 to 12 bits long).
  980.  *
  981.  * Note: accum must be at least 19 bits long. accum and bits must be
  982.  * re-initialized when EOFCode is written out.
  983.  */
  984.  
  985. static void
  986. output_lzw_code(register unsigned int code)
  987. {
  988.     static unsigned int bytes, bits;
  989.     static unsigned char bbuf[255 + 3];
  990.     static unsigned long accum;
  991.     register unsigned char *ch;
  992.  
  993.  
  994.     accum &= gif_codemask[bits];
  995.     accum |= (code << bits);
  996.     bits += CodeSize;
  997.  
  998.     ch = bbuf + bytes;
  999.     bytes += bits >> 3;
  1000.  
  1001.     while (bits >= 8)
  1002.       {
  1003.       bits -= 8;
  1004.       *ch++ = (accum & 255);
  1005.       accum >>= 8;
  1006.       }
  1007.  
  1008.     if (bytes >= 254 || code == EOFCode)
  1009.       {
  1010.       if (code == EOFCode && bits)
  1011.         {
  1012.         *ch = (accum & 255);
  1013.         bytes++;
  1014.         bits = accum = 0;
  1015.         }
  1016.       putc(bytes, fp);
  1017.       (void) fwrite(bbuf, 1, bytes, fp);
  1018.       bytes = 0;
  1019.       }
  1020. }
  1021.  
  1022. /*
  1023.  * Hand one scan line a time to the compressor.
  1024.  */
  1025. static ci_t *
  1026. get_scan_line(IPTR im, int i)
  1027. {
  1028.     int k = next_lineno(i, im->h, interlace);
  1029.     return ((ci_t **) im->mraster)[im->h - 1 - k];
  1030. }
  1031.  
  1032. #endif /* !NO_GIF */
  1033.